package cn.com.dhcc.turbo.service.registry;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import cn.com.dhcc.app.core.CM;
import cn.com.dhcc.app.core.dao.CrudDao;
import cn.com.dhcc.app.core.exception.DaoException;
import cn.com.dhcc.app.core.exception.NiceException;
import cn.com.dhcc.app.core.exception.ServiceException;
import cn.com.dhcc.app.core.handler.cachehandler.CacheHandler.CacheOperType;
import cn.com.dhcc.app.core.handler.modulehandler.WhereCondition;
import cn.com.dhcc.app.core.handler.pagerhandler.Pager;
import cn.com.dhcc.app.core.handler.pagerhandler.PagerData;
import cn.com.dhcc.app.core.service.AbstractCrudService;
import cn.com.dhcc.app.core.tag.CommonStaticCode.YESNO;
import cn.com.dhcc.app.core.util.JsonUtil;
import cn.com.dhcc.app.core.util.UUIDGenerator;
import cn.com.dhcc.app.pub.core.consts.AppIocBean;
import cn.com.dhcc.app.pub.core.consts.NodeInfoParam;
import cn.com.dhcc.app.pub.core.service.TurboCacheService;
import cn.com.dhcc.app.pub.core.service.TurboCacheService.KEY_VALUE_TYPE;
import cn.com.dhcc.turbo.dao.registry.NodePipelineDao;
import cn.com.dhcc.turbo.entity.registry.NodeInfo;
import cn.com.dhcc.turbo.entity.registry.NodePipeline;
import cn.com.dhcc.turbo.entity.registry.NodePipeline.PIPE_STATUS;
import cn.com.dhcc.turbo.entity.registry.NodePipeline.PIPE_TYPE;
import cn.com.dhcc.turbo.entity.registry.SynchronizeInfo.SyncOperType;
import cn.com.dhcc.turbo.entity.registry.SynchronizeInfo.SyncType;
import cn.com.dhcc.turbo.service.registry.sync.SynchronizeHandler;
import cn.com.dhcc.turbo.service.registry.vo.PipeLineFtp;
import cn.com.dhcc.turbo.service.registry.vo.PipeLineTlq;

/**
 * 传输通道service
 * 
 * @日期：2014-5-20 下午2:11:46
 * @作者：张洪涛
 * @版权所有：东华软件
 * @版本：1.0
 */
@Service
public class NodePipelineService extends AbstractCrudService<NodePipeline> {
	@Autowired
	@Qualifier(AppIocBean.TURBO_CACHE_SERVICE)
	private TurboCacheService turboCacheService;
	@Autowired
	private NodePipelineDao nodePipelineDao;
	@Autowired
	SynchronizeHandler synchronizeHandler;
	@Autowired
    NodeInfoService nodeInfoService;
	
	/**
	 * 获取tlq通道信息
	 * @return
	 */
	public List<PipeLineTlq> listPipelineTlq() throws ServiceException {
		List<PipeLineTlq> list=new ArrayList<PipeLineTlq>();
			try {
				List<NodePipeline> lines=nodePipelineDao.getLocalTlqPiplines();
				for (NodePipeline nodePipeline : lines) {
					list.add(JsonUtil.toObject(nodePipeline.getParamStr(),PipeLineTlq.class));
				}
			} catch (DaoException e) {
				throw new ServiceException("获取传输通道信息列表失败", e);
			}
			return list;
	}
	
	public PagerData<NodePipeline> list(Pager pager, WhereCondition condition)
			throws ServiceException {
		try {
			return nodePipelineDao.list(pager, condition);
		} catch (DaoException e) {
			throw new ServiceException("获取传输通道信息列表失败", e);
		}
	}
	public List<NodePipeline> getAll()
			throws ServiceException {
		try {
			return nodePipelineDao.getAll();
		} catch (DaoException e) {
			throw new ServiceException("获取所有通道信息失败", e);
		}
	}
	@Override
	public int insertOrUpdate(NodePipeline bean) throws ServiceException {
		int n = super.insertOrUpdate(bean);
		return n;
	}
	/**
	 * 接收同步过来的节点信息
	 * @param bean
	 * @return
	 * @throws ServiceException
	 */
	public int insertOrUpdateRemotePipeLine(NodePipeline bean) throws ServiceException {
		int n = super.insertOrUpdate(bean);
		NodeInfo nodeInfo = nodeInfoService.get(bean.getId());
		if(nodeInfo!=null){
			turboCacheService.updateFtpCache(CacheOperType.DELETE,null,nodeInfo.getNodeCode());
		}
		return n;
	}
	public int insertOrUpdateAndSync(NodePipeline bean) throws ServiceException, NiceException {
		int n = super.insertOrUpdate(bean);
		try {
			synchronizeHandler.syncToAllNodesFromLocalNode(SyncType.PILE_LINE, false, bean, SyncOperType.UPDATE,true);
		} catch (Exception e) {
			//同步出错，仍然可以进行其他操作
		}
		return n;
	}

	/**
	 * 获取节点已配置传输通道列表
	 * @param nodeId
	 * @return
	 * @throws ServiceException
	 */
	public List<NodePipeline> getNodePipelineByNodeId(String nodeId) throws ServiceException {
		try {
			return nodePipelineDao.getNodePipelineByNodeId(nodeId);
		} catch (DaoException e) {
			throw new ServiceException("获取节点已配置传输通道列表失败", e);
		}
	}
	/**
	 * 获取节点已配置传输通道列表
	 * @param nodeId
	 * @return
	 * @throws ServiceException
	 */
	public List<NodePipeline> getLocalNodePipeline() throws ServiceException {
		try {
			return nodePipelineDao.getLocalNodePipeline();
		} catch (DaoException e) {
			throw new ServiceException("获取节点已配置传输通道列表失败", e);
		}
	}
	/**
	 * 根据通道id获取本地通道信息
	 * @param id
	 * @return
	 * @throws DaoException
	 * @throws ServiceException
	 */
	public NodePipeline getLocalNodePipelineById(String id) throws DaoException, ServiceException{
		try {
			return nodePipelineDao.getLocalNodePipelineById(id);
		} catch (DaoException e) {
			throw new ServiceException(e);
		}
	}
	/**
	 * 更具节点编码获取ftp到信息
	 * @return
	 * @throws ServiceException 
	 */
	public PipeLineFtp getFtpConfByNodeId(String nodeId) throws ServiceException{
		WhereCondition searchParameter = new WhereCondition();
		searchParameter.where().eq("PIPETYPE", PIPE_TYPE.FTP_EMBED.getCode()).and().eq("node_id", nodeId);
		try {
			NodePipeline nodePipeline = CM.getDao().getModule("获取ftp配置信息", NodePipeline.class, searchParameter);
			if(nodePipeline==null)return null;
			String para = nodePipeline.getParamStr();
			return JsonUtil.toObject(para, PipeLineFtp.class);
		} catch (DaoException e) {
			throw new ServiceException("获取内置的ftp配置信息失败", e);
		}
	}
	/**
	 * 获取本地ftp信息
	 * @return
	 * @throws ServiceException 
	 */
	public PipeLineFtp getLocalFtpConf() throws ServiceException{
		WhereCondition searchParameter = new WhereCondition();
		searchParameter.where().eq("PIPETYPE", PIPE_TYPE.FTP_EMBED.getCode()).and().eq("islocal", YESNO.YES.getStatus());
		try {
			NodePipeline nodePipeline = CM.getDao().getModule("获取本地ftp配置信息", NodePipeline.class, searchParameter);
			if(nodePipeline==null)return null;
			String para = nodePipeline.getParamStr();
			return JsonUtil.toObject(para, PipeLineFtp.class);
		} catch (DaoException e) {
			throw new ServiceException("获取内置的ftp配置信息失败", e);
		}
	}
	public NodePipeline get(String id) throws ServiceException {
		try {
			return nodePipelineDao.get(id);
		} catch (DaoException e) {
			throw new ServiceException("获取传输通道失败", e);
		}
	}
	
	/**
	 * 根据nodeId tlq通道ip查询一个对象
	 * @param id
	 * @param ip
	 * @return
	 * @throws ServiceException
	 */
	public NodePipeline getByNodeIdAndIp(String nodeId,String ip) throws ServiceException {
		try {
			return nodePipelineDao.getByNodeIdAndIp(nodeId,ip);
		} catch (DaoException e) {
			throw new ServiceException("获取传输通道失败", e);
		}
	}
	
	public NodePipeline getEmbedPipeLine(String nodeId,PIPE_TYPE type) throws ServiceException{
		WhereCondition searchParameter = new WhereCondition();
		searchParameter.where().eq("PIPETYPE", type.getCode()).and().eq("node_id", nodeId)
		.and().eq("ISEMBED", YESNO.YES.getStatus());
		try {
			return CM.getDao().getModule("获取内置的通道配置信息", NodePipeline.class, searchParameter);
		} catch (DaoException e) {
			throw new ServiceException("获取通道信息配置失败", e);
		}	
	}
	public NodePipeline getLocalEmbedPipeLine(PIPE_TYPE type) throws ServiceException{
		WhereCondition searchParameter = new WhereCondition();
		searchParameter.where().eq("PIPETYPE", type.getCode()).and().eq("islocal", YESNO.YES.getStatus())
		.and().eq("ISEMBED", YESNO.YES.getStatus());
		try {
			return CM.getDao().getModule("获取内置的通道配置信息", NodePipeline.class, searchParameter);
		} catch (DaoException e) {
			throw new ServiceException("获取通道信息配置失败", e);
		}	
	}
	/**
	 * 获取内嵌的Ftp配置
	 * @return
	 * @throws ServiceException 
	 */
	public NodePipeline saveOrUpdateEmbedFtpConf(NodeInfo localNode,PipeLineFtp pipeLineFtp,PIPE_STATUS status) throws ServiceException{
		
		try {
			NodePipeline nodePipeline = getEmbedPipeLine(localNode.getId(), PIPE_TYPE.FTP_EMBED);
			if(nodePipeline==null){
				nodePipeline = new NodePipeline(); 
				nodePipeline.setId(UUIDGenerator.getUUID());
				nodePipeline.setIsEmbed(YESNO.YES.getStatus());
				nodePipeline.setIsLocal(YESNO.YES.getStatus());
				nodePipeline.setNodeId(localNode.getId());
				nodePipeline.setPipeType(PIPE_TYPE.FTP_EMBED.getCode());
			}
			nodePipeline.setMtime(new Date());
			nodePipeline.setStatus(status.getCode());
			nodePipeline.setParamStr(JsonUtil.toJson(pipeLineFtp));
			insertOrUpdate(nodePipeline);
			turboCacheService.updateFtpCache(CacheOperType.UPDATE, pipeLineFtp, localNode.getNodeCode());
			return nodePipeline;
		} catch (Exception e) {
			throw new ServiceException("改内置ftp配置失败", e);
		}
	}
	/**
	 * 获取本地内嵌的Ftp配置
	 * @return
	 * @throws ServiceException 
	 */
	public NodePipeline saveOrUpdateLocalEmbedFtpConf(PipeLineFtp pipeLineFtp,PIPE_STATUS status) throws ServiceException{
		try {
			NodePipeline nodePipeline = getLocalEmbedPipeLine(PIPE_TYPE.FTP_EMBED);
			if(nodePipeline==null){
				nodePipeline = new NodePipeline(); 
				nodePipeline.setId(UUIDGenerator.getUUID());
				nodePipeline.setIsEmbed(YESNO.YES.getStatus());
				nodePipeline.setIsLocal(YESNO.YES.getStatus());
				nodePipeline.setPipeType(PIPE_TYPE.FTP_EMBED.getCode());
			}
			nodePipeline.setMtime(new Date());
			nodePipeline.setStatus(status.getCode());
			nodePipeline.setParamStr(JsonUtil.toJson(pipeLineFtp));
			
			NodeInfo localNode = nodeInfoService.getLocalNode();
			if(localNode!=null){
				nodePipeline.setNodeId(localNode.getId());
			}
			insertOrUpdate(nodePipeline);
			if(localNode!=null){
				turboCacheService.updateFtpCache(CacheOperType.UPDATE, pipeLineFtp, localNode.getNodeCode());
			}
			return nodePipeline;
		} catch (Exception e) {
			throw new ServiceException("改内置ftp配置失败", e);
		}
	}
	/**
	 * 修改ftp状态,并同步
	 * @return
	 * @throws ServiceException 
	 */
	public void updateFtpStatusAndSync(String nodeId,PIPE_STATUS status) throws ServiceException{
		try {
			NodePipeline nodePipeline = getEmbedPipeLine(nodeId, PIPE_TYPE.FTP_EMBED);
			nodePipeline.setMtime(new Date());
			nodePipeline.setStatus(status.getCode());
			insertOrUpdateAndSync(nodePipeline);
		} catch (Exception e) {
			throw new ServiceException("改内置ftp配置失败", e);
		}
	}
	/**
	 * 修改ftp状态
	 * @return
	 * @throws ServiceException 
	 */
	public void updateFtpStatus(String nodeId,PIPE_STATUS status) throws ServiceException{
		try {
			NodePipeline nodePipeline = getEmbedPipeLine(nodeId, PIPE_TYPE.FTP_EMBED);
			nodePipeline.setMtime(new Date());
			nodePipeline.setStatus(status.getCode());
			super.insertOrUpdate(nodePipeline);
		} catch (Exception e) {
			throw new ServiceException("改内置ftp配置失败", e);
		}
	}
	/**
	 * 修改ftp状态
	 * @return
	 * @throws ServiceException 
	 */
	public void updateLocalFtpStatus(PIPE_STATUS status) throws ServiceException{
		try {
			NodeInfo nodeInfo = nodeInfoService.getLocalNode();
			if(NodeInfoParam.isMwr() && nodeInfo != null){
				updateFtpStatus(nodeInfo.getId(), status);
			}else{
				NodePipeline nodePipeline = getLocalEmbedPipeLine(PIPE_TYPE.FTP_EMBED);
				nodePipeline.setMtime(new Date());
				nodePipeline.setStatus(status.getCode());
				super.insertOrUpdate(nodePipeline);
			}
		} catch (Exception e) {
			throw new ServiceException("改内置ftp配置失败", e);
		}
	}
	/**
	 * 修改本地节点的节点id，因为系统还没在管理节点注册时，本地的通道信息时没有节点id的
	 * @param owner
	 * @throws DaoException
	 */
	public void updateNodePipeLineOwner(NodeInfo owner) throws ServiceException{
		try {
			nodePipelineDao.updateNodePipeLineOwner(owner);
		} catch (DaoException e) {
			throw new ServiceException(e);
		}
	}
	public PipeLineTlq getTlqPipeLineByNodeCode(String nodeCode) throws ServiceException {
		try {
			NodeInfo nodeInfo = getNodeInfoByCode(nodeCode);
			return  JsonUtil.toObject(nodePipelineDao.getTlqPipline(nodeInfo.getId()).getParamStr(),PipeLineTlq.class);
		} catch (DaoException e) {
			throw new ServiceException(e);
		}
	}
	@Override
	public CrudDao<NodePipeline> getCrudDao() {
		return nodePipelineDao;
	}
	public NodeInfo getNodeInfoByCode(String nodeCode) throws ServiceException {
		NodeInfo nodeInfo = (NodeInfo) turboCacheService.getData("根据编码获取节点", KEY_VALUE_TYPE.NODE_CODE__NODEINFO, nodeCode);
		if (nodeInfo == null) {
			try {
				nodeInfo = nodeInfoService.getByUniqueProperty("node_code", nodeCode);
			} catch (ServiceException e) {
				throw e;
			}
			
			if(nodeInfo != null){
				turboCacheService.putData("插入节点信息缓存对象code:" + nodeCode, KEY_VALUE_TYPE.NODE_CODE__NODEINFO, nodeCode, nodeInfo);
			}
		}
		return nodeInfo;
	}
	/**
	 * 根据节点编码获取对应TLQ的节点信息
	 * @return
	 * @throws ServiceException
	 */
	public NodePipeline getLocalTlqPipline() throws ServiceException {
		try {
			return nodePipelineDao.getLocalTlqPipline();
		} catch (DaoException e) {
			throw new ServiceException(e);
		}
	}
}
